package com.value.mybatis;


import com.value.mybatis.utils.MyBatisHelper;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import javax.xml.bind.PropertyException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class CountPlugin implements Interceptor {


    private static String dialect = "";
    private static String pageSqlId = "";


    public static String MYBATIS_COUNT_KEY = "MYBATIS_COUNT_KEY";


    public Object intercept(Invocation ivk) throws Throwable {
        //当前环境 MappedStatement，BoundSql，及sql取得
        MappedStatement mappedStatement = (MappedStatement) ivk.getArgs()[0];
        if (!mappedStatement.getId().matches(pageSqlId)) {
            return ivk.proceed();
        }
        Object parameter = ivk.getArgs()[1];
        if (parameter == null || !(parameter instanceof Map)) {
            return ivk.proceed();
        } else {
            BoundSql boundSql = mappedStatement.getBoundSql(parameter);
//            Object parameterObject = boundSql.getParameterObject();

            Map params = (Map) parameter;
            if(!params.containsKey(MYBATIS_COUNT_KEY)){
                return ivk.proceed();
            }
            //获取链接
            //统计count
            String sql = boundSql.getSql();
            String countSql = "select count(0) from (" + sql + ") myCount";
            BoundSql newBoundSql = MyBatisHelper.copyFromBoundSql(mappedStatement, boundSql, countSql);

            List<ResultMap> resultMaps = new ArrayList<>();
            List<ResultMapping> resultMappings=new ArrayList<>();
            ResultMap resultMap = new ResultMap.Builder(mappedStatement.getConfiguration(), mappedStatement.getId(), Integer.class, resultMappings).build();
            resultMaps.add(resultMap);
            ivk.getArgs()[0] = MyBatisHelper.copyFromMappedStatement(mappedStatement,new BoundSqlSource(newBoundSql),resultMaps);
        }
        return ivk.proceed();
    }


    public Object plugin(Object arg0) {
        // TODO Auto-generated method stub
        return Plugin.wrap(arg0, this);
    }

    public void setProperties(Properties p) {
        pageSqlId = p.getProperty("pageSqlId");
        if (pageSqlId == null || pageSqlId.equals("")) {
            try {
                throw new PropertyException("pageSqlId property is not found!");
            } catch (PropertyException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}